<?php declare(strict_types=1);

namespace Zyucv7\Core\Web\Response;

use Zyucv7\Core\Web\Response;
use Zyucv7\Core\Web\Exceptions\ResponseException;

/**
 * JSON 响应类
 * 
 * 提供便捷的方法来生成和发送 JSON 格式的 HTTP 响应
 */

class JsonResponse {

    // HTTP状态码常量
    private const JSON_OK = 0;
    private const JSON_ERR = -1;
    public const CONTENT_TYPE_JSON = 'application/json; charset=utf-8';

    /**
     * 设置响应内容为JSON字符串
     * 
     * @param mixed $data 要转换为JSON的数据
     * @param int $options JSON编码选项
     * @param int $depth JSON编码最大深度
     * @throws InvalidArgumentException 如果数据无法编码为JSON
     */
    private static function setContent(
        $data,
        int $options = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
        int $depth = 512
    ) {
        // 处理特殊的数据类型
        if ($data instanceof \JsonSerializable) {
            // 已经实现了JsonSerializable接口
        } elseif (is_resource($data)) {
            throw ResponseException::InvalidArgument('Resources cannot be encoded to JSON');
        }
        
        $json = json_encode($data, $options, $depth);
        
        if ($json === false) {
            $error = json_last_error_msg();
            throw ResponseException::InvalidArgument("JSON encoding failed: {$error}");
        }
        
        // 验证生成的JSON是否有效
        if (json_decode($json) === null && $data !== null) {
            throw ResponseException::InvalidArgument('Generated JSON is invalid');
        }
        
        $response = Response::instance();
        $response->setStatusCode(Response::HTTP_OK);
        $response->setContent($json, self::CONTENT_TYPE_JSON);
        $response->addHeader('Content-Length', (string)strlen($json));

        return $response;
    }
    
    /**
     * 发送JSON响应并终止脚本
     * 
     * @param mixed $data
     * @param int $statusCode
     * @param int $options
     * @param int $depth
     * @return void
     */
    public static function send($data): void
    {
        self::setContent($data)->send(true);
    }

    /**
     * 发送错误JSON响应
     * 
     * @param string $message 错误消息
     * @param int $statusCode HTTP状态码
     * @param array $additionalData 额外的错误数据
     * @return void
     */
    public static function error(string $message, array $additionalData = []): void
    {
        $errorData = [
            'error' => true,
            'msg' => $message,
            'code' => self::JSON_ERR,
            'timestamp' => time()
        ];
        
        if (!empty($additionalData)) {
            $errorData['details'] = $additionalData;
        }

        self::send($errorData);
    }
    
    /**
     * 发送成功JSON响应
     * 
     * @param mixed $data 响应数据
     * @param string $message 成功消息
     * @return void
     */
    public static function success($data = null): void
    {
        $responseData = [
            'success' => true,
            'msg' => 'OK',
            'code' => self::JSON_OK,
            'data' => $data,
            'timestamp' => time()
        ];
        
        self::send($responseData);
    }
    
}